package models.outstock

import java.sql.Timestamp
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

import javax.inject.{Inject, Singleton}
import play.api.Logging
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import services.OutStockPostParameters
import slick.jdbc.JdbcProfile
import slick.sql.SqlProfile.ColumnOption.SqlType

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}

/**
 * 销售发货单ORM
 *
 * @param dbConfigProvider
 * @param executionContext
 */
@Singleton
class OutStockRevRepository @Inject()(
                                       protected val dbConfigProvider: DatabaseConfigProvider
                                     )(implicit executionContext: ExecutionContext)
  extends HasDatabaseConfigProvider[JdbcProfile] with Logging {

  import profile.api._

  // These imports are important, the first one brings db into scope, which will let you do the actual db operations.
  // The second one brings the Slick DSL into scope, which lets you define the table and other queries.

  /**
   * private class PeopleTable(tag: Tag) extends Table[Person](tag, "people")
   *
   * @param tag
   */
  private class OutStockRevTable(tag: Tag) extends Table[OutStockRecive](tag, "OutStockRev".toUpperCase) {
    def id = column[Option[Int]]("id".toUpperCase, O.PrimaryKey, O.AutoInc)

    def outStockSumId = column[Option[Int]]("OutStockSumId".toUpperCase)

    def fEntity = column[Boolean]("FEntity".toUpperCase)

    def fDate = column[Timestamp]("FDate".toUpperCase, SqlType("timestamp not null default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP"))

    def fGYBillNo = column[String]("FGYBillNo".toUpperCase)

    def fShopNumber = column[String]("FShopNumber".toUpperCase)

    def fStockNumber = column[String]("FStockNumber".toUpperCase)

    def sumStatus = column[Int]("SumStatus".toUpperCase)

    def fEntityInfo = column[Option[String]]("FEntityInfo".toUpperCase)

    /**
     *
     * @return
     */
    def * = (
      id, outStockSumId, fEntity, fDate, fGYBillNo, fShopNumber, fStockNumber, sumStatus, fEntityInfo
      ).<>((OutStockRecive.apply _).tupled, OutStockRecive.unapply)

  }

  private val outStockRev = TableQuery[OutStockRevTable]

  /**
   *
   * @return
   */
  def listAll(): Future[Seq[OutStockRecive]] = db.run {
    outStockRev.result
  }

  def reciveOSR(rev: OutStockRecive) = db.run {
    (outStockRev returning outStockRev.map(_.id)) += rev
  }

  def insertOSR(rev: OutStockRecive) = db.run {
    outStockRev.filter(_.fGYBillNo === rev.osrFGYBillNo).result
  }.flatMap { f =>
    if (f.nonEmpty) Future(f.head.osrid)
    else db.run((outStockRev returning outStockRev.map(_.id)) += rev)
  }

  def findByFGYBillNo(filter: String) = {
    val a = for (c <- outStockRev if c.fGYBillNo === filter) yield c.fGYBillNo
    db.run(a.result)
  }

  def list(p: OutStockPostParameters) = {
    val dtformat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
    val offset = p.limit * p.page
    val p2 = "[0-9]".r.findAllIn(p.p2).mkString
    val pOutStockSumId = if (p.p2 == "") 0 else p2.toInt
    //    try {
    //      pOutStockSumId = p.p2.substring(4).toInt
    //    } catch {
    //      case e: Exception => logger.debug(s"OSR_OutStockSumId=p.p2.substring(4).toInt",e)
    //    }
    val pFGYBillNo = p.p1
    val datestart = Timestamp.valueOf(LocalDateTime.parse(p.sdate.substring(0, 19)))
    val dateend = Timestamp.valueOf(LocalDateTime.parse(p.sdate.substring(22)))

    val f = outStockRev.filterIf(pFGYBillNo.nonEmpty)(_.fGYBillNo === pFGYBillNo)
      .filterIf(p.p2.nonEmpty)(_.outStockSumId.getOrElse(0) === pOutStockSumId)
      .filterIf(pFGYBillNo.isEmpty && p.p2.isEmpty)(_.fDate >= datestart)
      .filterIf(pFGYBillNo.isEmpty && p.p2.isEmpty)(_.fDate < dateend)
      .filterIf(p.status == 0 || p.status == 2)(_.sumStatus === p.status)
      .filterIf(p.status == 1)(_.sumStatus < 0)
    val res = f.sortBy(_.id).drop(offset).take(p.limit).map(f => f).result
    val total = f.length.result
    db.run(res).zip(db.run(total))
  }

  def osrSumFindByDate(arg_Date: LocalDateTime, thisSumStatus: Int, arg_FStockNumberdate: Option[String] = None) = {
    val datestart = Timestamp.valueOf(arg_Date)
    val dateend = Timestamp.valueOf(arg_Date.plusDays(1))
    val f = outStockRev
      .filterIf(true)(_.fDate >= datestart)
      .filterIf(true)(_.fDate < dateend)
      .filterOpt(arg_FStockNumberdate)(_.fStockNumber === _)
      .filterIf(true)(_.sumStatus < 2)
      .sortBy(_.id)

    Await.result(db.run(f.map(osr => osr.sumStatus).update(thisSumStatus)), Duration.Inf)
    Await.result(db.run(f.map(f => f).result), Duration.Inf)

  }

  def osrSumUpdateEnd(sup: OutStockRecive) = db.run {
    val f = outStockRev
      .filterOpt(sup.osrid)(_.id === _)
      .filterIf(sup.osrFShopNumber != "")(_.fShopNumber === sup.osrFShopNumber)
      .filterIf(sup.osrFStockNumber != "")(_.fStockNumber === sup.osrFStockNumber)
      .filterIf(sup.osrSumStatus < 0)(_.sumStatus === sup.osrSumStatus)

    f.map(osr => (osr.outStockSumId, osr.sumStatus)).update((sup.osrOutStockSumId, 2))
  }

  def osrStockCodes = db.run(outStockRev.filter(_.sumStatus =!= 2).map(_.fStockNumber).distinct.result)

}
